const path = require('path');
const fs = require('fs');
const http = require('http');
const express = require('express');
const { Server } = require('socket.io');
const QRCode = require('qrcode');
const VotingState = require('./src/votingState');

function loadConfig(customConfigPath) {
  const resolvedPath = customConfigPath
    ? path.resolve(customConfigPath)
    : path.join(__dirname, 'config.json');
  const fileContents = fs.readFileSync(resolvedPath, 'utf-8');
  const config = JSON.parse(fileContents);
  return { config, resolvedPath };
}

function createVotingServer(options = {}) {
  const { configPath: customConfigPath, port: forcedPort } = options;
  const { config } = loadConfig(customConfigPath);
  const app = express();
  const httpServer = http.createServer(app);
  const io = new Server(httpServer, { cors: { origin: '*' } });
  const votingState = new VotingState(config);

  let latestSnapshot = votingState.getState();

  app.use(express.json());
  // 首页特殊处理，显示投票列表
  app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'public', 'index.html'));
  });
  app.use(express.static(path.join(__dirname, 'public')));

  function broadcastState() {
    latestSnapshot = votingState.getState();
    io.emit('state:update', latestSnapshot);
  }

  app.get('/api/state', (req, res) => {
    const snapshot = votingState.getState();
    latestSnapshot = snapshot;
    res.json(snapshot);
  });

  // 获取本机局域网IP
  // 直接使用公网IP生成二维码
  app.get('/api/qr', async (req, res) => {
    try {
      const publicHost = '8.148.206.251';
      const port = req.app.get('port') || (process.env.PORT || config.port || 80);
      // 80端口时不加端口号
      const voteUrl = port == 80
        ? `http://${publicHost}/vote.html`
        : `http://${publicHost}:${port}/vote.html`;
      const dataUrl = await QRCode.toDataURL(voteUrl, { margin: 1, width: 360 });
      res.json({ url: voteUrl, dataUrl });
    } catch (error) {
      res.status(500).json({ error: '二维码生成失败', details: error.message });
    }
  });

  app.post('/api/vote', (req, res) => {
    const { participantId } = req.body || {};
    const result = votingState.vote(participantId);
    if (!result.accepted) {
      const statusCode = result.reason === 'voting_closed' ? 403 : 400;
      res.status(statusCode).json({ ok: false, reason: result.reason });
      return;
    }
    broadcastState();
    res.json({ ok: true, participant: result.participant });
  });

  app.post('/api/control/reset', (req, res) => {
    try {
      const { participants, durationSeconds } = req.body || {};
      votingState.reset({ participants, durationSeconds });
      broadcastState();
      res.json(votingState.getState());
    } catch (error) {
      res.status(400).json({ error: error.message });
    }
  });

  io.on('connection', (socket) => {
    socket.emit('state:update', latestSnapshot);
  });

  const ticker = setInterval(() => {
    const previousStatus = latestSnapshot.status;
    const snapshot = votingState.getState();
    latestSnapshot = snapshot;
    if (snapshot.status !== previousStatus || snapshot.status === 'open') {
      io.emit('state:update', snapshot);
    }
  }, 1000);

  const port = forcedPort !== undefined
    ? Number(forcedPort)
    : Number(process.env.PORT || config.port || 80);

  function start() {
    return new Promise((resolve) => {
      httpServer.listen(port, '0.0.0.0', () => {
        const address = httpServer.address();
        const actualPort = typeof address === 'object' && address ? address.port : port;
        app.set('port', actualPort);
        const publicHost = '8.148.206.251';
        console.log(`实时投票服务已启动: http://localhost:${actualPort}`);
        if (actualPort == 80) {
          console.log(`公网扫码地址:   http://${publicHost}/vote.html`);
        } else {
          console.log(`公网扫码地址:   http://${publicHost}:${actualPort}/vote.html`);
        }
        resolve({
          port: actualPort
        });
      });
    });
  }

  function stop() {
  clearInterval(ticker);
    io.removeAllListeners();
    return new Promise((resolve, reject) => {
      httpServer.close((error) => {
        if (error) {
          reject(error);
          return;
        }
        resolve();
      });
    });
  }

  return {
    app,
    io,
    httpServer,
    start,
    stop,
    votingState
  };
}

if (require.main === module) {
  const server = createVotingServer();
  server
    .start()
    .then(({ port }) => {
      console.log('使用浏览器打开计分大屏: http://localhost:%d/scoreboard.html', port);
      console.log('投票页面（可生成二维码）: http://localhost:%d/vote.html', port);
    })
    .catch((error) => {
      console.error('服务器启动失败', error);
      process.exitCode = 1;
    });

  const shutdown = async () => {
    console.log('\n正在关闭服务...');
    try {
      await server.stop();
      process.exit(0);
    } catch (error) {
      console.error('关闭失败', error);
      process.exit(1);
    }
  };

  process.on('SIGINT', shutdown);
  process.on('SIGTERM', shutdown);
}

module.exports = {
  createVotingServer
};
